package com.xxx.work;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

/**
 * Rabbit MQ使用场景二：work模式，1个生产者，多个消费者（多对多）
 * 生产者批量往mq里发送消息
 * 
 * 测试结果：
 * 	1、消费者1和消费者2获取到的消息内容是不同的，同一个消息只能被一个消费者获取。
	2、消费者1和消费者2获取到的消息的数量是相同的，一个是消费奇数号消息，一个是偶数。
	其实，这样是不合理的，因为消费者1线程停顿的时间短。应该是消费者1要比消费者2获取到的消息多才对。
	RabbitMQ 默认将消息顺序发送给下一个消费者，这样，每个消费者会得到相同数量的消息。即轮询（round-robin）分发消息。
	怎样才能做到按照每个消费者的能力分配消息呢？
		联合使用 Qos 和 Acknowledge 就可以做到。
		basicQos 方法设置了当前信道最大预获取（prefetch）消息数量为1。消息从队列异步推送给消费者，消费者的 ack 也是异步发送给队列，
		从队列的视角去看，总是会有一批消息已推送但尚未获得 ack 确认，Qos 的 prefetchCount 参数就是用来限制这批未确认消息数量的。
		设为1时，队列只有在收到消费者发回的上一条消息 ack 确认后，才会向该消费者发送下一条消息。
		prefetchCount 的默认值为0，即没有限制，队列会将所有消息尽快发给消费者。
 * 
 * @author guweiqiang
 * 2018年6月13日
 */
public class Producer {
	
	private static final String QUEUE_NAME = "work_queue";
//	private static final String HOST = "localhost";

	public static void main(String[] args) throws IOException, TimeoutException {
		// 1.创建连接工厂，并设置工厂相关属性
		ConnectionFactory factory = new ConnectionFactory();
//		factory.setHost(HOST); // 默认为localhost
		
		// 2.创建一个连接
		Connection connection = factory.newConnection();
		
		// 3.创建一个通道
		Channel channel = connection.createChannel();
		
		// 4.声明一个队列
		channel.queueDeclare(QUEUE_NAME, false, false, false, null);
		channel.basicQos(1); // sender 每次只分发一个消息，接收到回执之后才会继续分发消息
		// 第一个参数表示队列名称
		// 第二个参数为是否需要持久化（true表示是，队列将在服务器重启时生成）
		// 第三个参数为是否是独占队列（创建者可以使用的私有队列，断开后自动删除）
		// 第四个参数为当所有消费者客户端连接断开时是否自动删除队列
		// 第五个参数为队列的其他参数
		
		// 5.往队列里发送消息
		for (int i=51; i<=100; i++) {
			String message = "hello rabbit mq" + i;
			channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes("UTF-8"));
			// 第一个参数为交换机名称（这里设置为空）
			// 第二个参数为队列映射的路由key（这里设置和队列名一样）
			// 第三个参数为消息的其他属性
			// 第四个参数为发送信息的主体
			System.out.println("Producer send message：" + message);
		}
		
		// 6.关闭连接
//		channel.close();
//		connection.close();
	}

}
